package com.wqnmdb.im.netty.init;

import com.wqnmdb.im.domain.netty.protobuf.NettyModel;
import com.wqnmdb.im.netty.handler.impl.AuthHandler;
import com.wqnmdb.im.netty.handler.impl.HeartbeatHandler;
import com.wqnmdb.im.netty.handler.impl.BusinessHandler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.protobuf.ProtobufDecoder;
import io.netty.handler.codec.protobuf.ProtobufEncoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
import io.netty.handler.timeout.IdleStateHandler;

import java.util.concurrent.TimeUnit;

/**
 * netty服务初始化器
 **/
public class ServerChannelInitializer extends ChannelInitializer<SocketChannel> {
    /**
     * 服务器读操作空闲(秒)
     */
    private final static int readerIdleTime = 0;
    /**
     * 服务器写操作空闲(秒)
     */
    private final static int writerIdleTime = 0;
    /**
     * 服务器全部操作空闲(秒)
     */
    private final static int allIdleTime = 30;

//    private final static int M = 1024 * 1024;

    @Override
    protected void initChannel(SocketChannel socketChannel) throws Exception {
        // 全局流量整形；writeLimit/readLimit{0 or a limit in bytes/s}
//        socketChannel.pipeline().addLast(
//                new GlobalTrafficShapingHandler(socketChannel.eventLoop().parent(), 5 * M, 10 * M));
        //处理半包消息
        socketChannel.pipeline().addLast(new ProtobufVarint32FrameDecoder());
        socketChannel.pipeline().addLast(new ProtobufDecoder(NettyModel.ReqModel.getDefaultInstance()));
        //在消息头上加上一个长度为32的整形字段，用于标志这个消息的长度
        socketChannel.pipeline().addLast(new ProtobufVarint32LengthFieldPrepender());
        socketChannel.pipeline().addLast(new ProtobufEncoder());

        // 心跳检测，如果在N分钟时没有向服务端发送读写心跳(ALL)，则主动断开 0代表不处理
        socketChannel.pipeline().addLast(
                new IdleStateHandler(readerIdleTime, writerIdleTime, allIdleTime, TimeUnit.SECONDS));
        // 权鉴处理器
        socketChannel.pipeline().addLast(new AuthHandler());
        // 心跳处理器
        socketChannel.pipeline().addLast(new HeartbeatHandler());
        // 业务处理器
        socketChannel.pipeline().addLast(new BusinessHandler());
    }
}
